/**
 * 
 */
package org.pdecodts.yasb.domain;

import java.util.Set;
import java.util.logging.Logger;

import org.pdecodts.yasb.util.Asserter;

/**
 * @author xsipds
 *
 */
public class BusinessProcess {
    private static Logger log = Logger.getLogger(BusinessProcess.class.toString()) ;
    /**
     * the name of the business process
     */
    private String name ;
    
    /**
     * The transitions defined inside the BP
     */
    private Set<Transition> transitions ;
    /**
     * The activities defined inside the BP
     */
    private Set<Activity> activities ;
    
    /**
     * @return the name
     */
    public String getName() {
        return name;
    }
    /**
     * @param name the name to set
     */
    public void setName(String name) {
        this.name = name;
    }
    /**
     * @return the transitions
     */
    public Set<Transition> getTransitions() {
        return transitions;
    }
    /**
     * @param transitions the transitions to set
     */
    public void setTransitions(Set<Transition> transitions) {
        this.transitions = transitions;
    }
    /**
     * @return the activities
     */
    public Set<Activity> getActivities() {
        return activities;
    }
    /**
     * @param activities the activities to set
     */
    public void setActivities(Set<Activity> activities) {
        this.activities = activities;
    }
    
    public void registerActivity(Activity activity) {
        this.activities.add(activity) ;
        activity.setContainer(this) ;
    }
    /**
     * Retrieved a registered activity by name
     * @param name the name of the activity to retrieve
     * @return the retrieved activity
     * @throws Exception in case of provided name is null or no related activity found
     */
    public Activity lookupActivity(String name) throws Exception {
        /*
         * Precondition
         * The name of the lookup actvitiy cannot be null
         */
        Asserter.precondition(log, name != null ,Exception.class, "name of looked up activity cannot be null",12) ;
        Activity res = null ; 
        for (Activity a : this.activities) {
            if (name.equals(a.getName())) {
                res = a ;
                break ;
            }
        }
        /*
         * Postcondition
         * The returned activity cannot be null
         */
        Asserter.precondition (log, res != null,  Exception.class, "no activity found for name '"+ name + "'", 12) ;
        return res ;
    }
    /**
     * Retrieved an registered transition by name
     * @param name the name of the transition to retrieve
     * @return the retrieved transtion
     * @throws Exception in case of provided name is null or no related transition found
     */
    public Transition lookupTransition(String name) throws Exception {
        /*
         * Precondition
         * The name of the lookup actvitiy cannot be null
         */
        Asserter.precondition(log, name != null ,Exception.class, "name of looked up transition cannot be null",12) ;
        Transition res = null ; 
        for (Transition a : this.transitions) {
            if (name.equals(a.getName())) {
                res = a ;
                break ;
            }
        }
        /*
         * Postcondition
         * The returned activity cannot be null
         */
        Asserter.precondition (log, res != null,  Exception.class, "no transition found for name '"+ name + "'", 12) ;
        return res ;
    }
    
    public void bind(String transitionName,  String sourceActivity, String targetActivity) throws Exception {
        Activity source = this.lookupActivity(sourceActivity) ;
        Activity target = this.lookupActivity(targetActivity) ;
        Transition trans = this.lookupTransition(transitionName) ;
        bind(trans, source, target) ;
     }
    /**
     * @param trans
     * @param source
     * @param target
     * @return
     * @throws Exception 
     */
    private void bind(Transition trans, Activity source, Activity target) throws Exception {
        
        Asserter.precondition(log, (trans.getContainer() != this), Exception.class, "transition '"+ trans.getName() + "' does not belong to the container", 12) ;
        Asserter.precondition(log, (source.getContainer() != this), Exception.class, "activity '"+ source.getName() + "' does not belong to the container", 12) ;
        Asserter.precondition(log, (target.getContainer() != this), Exception.class, "activity '"+ target.getName() + "' does not belong to the container", 12) ;
        
        Asserter.alert(log, (trans.getSource() != null && trans.getSource() != source ), "source for transition '"+ trans.getName() + "' already define and will be overriden", 20) ;
        Asserter.alert(log, (trans.getTarget() != null && trans.getTarget() != target ), "target for transition '"+ trans.getName() + "' already define and will be overriden", 20) ;
        
        
        if (!source.getOutgoingTransitions().contains(trans)) {
        source.addOutgoingTransition(trans) ;
        }
        else {
            Asserter.alert(log, true, "transition already declared as outgoing ", 30) ;
        }
        if (!target.getIncomingTransitions().contains(trans)) {
        target.addIncomingTransition(trans) ;
        
        }
        else {
            Asserter.alert(log, true, "transition already declared as incoming ", 30) ;
        }
        
        trans.setSource(source) ;
        trans.setTarget(target) ;
        
    }
    
    
    
    
    
    
}
